package com.kele.message.response;

import com.kele.message.base.ResponseFrame;
import com.kele.message.response.read.ReadCoilsResponseFrame;
import com.kele.message.response.read.ReadHoldingRegistersResponseFrame;
import com.kele.message.response.write.*;
import com.kele.constants.ModbusFunction;

import java.util.HashMap;
import java.util.Map;

public class ResponseFrameFactory {

    private static final Map<Integer, Class<? extends ResponseFrame>> messageClasses = new HashMap<>();

    /**
     * 根据功能码，获得对应的消息 class
     * @param functionCode 功能码
     * @return 消息 class
     */
    public static Class<? extends ResponseFrame> getMessageClass(int functionCode) {
        return messageClasses.get(functionCode);
    }

    static {
        // 01
        messageClasses.put(ModbusFunction.READ_COILS, ReadCoilsResponseFrame.class);
        // 02
        messageClasses.put(ModbusFunction.READ_DISCRETE_INPUTS, ReadCoilsResponseFrame.class);
        // 03
        messageClasses.put(ModbusFunction.READ_HOLDING_REGISTERS, ReadHoldingRegistersResponseFrame.class);
        // 04
        messageClasses.put(ModbusFunction.READ_INPUT_REGISTERS, ReadHoldingRegistersResponseFrame.class);
        // 05
        messageClasses.put(ModbusFunction.WRITE_SINGLE_COIL, WriteSingleCoilResponseFrame.class);
        // 06
        messageClasses.put(ModbusFunction.WRITE_SINGLE_REGISTER, WriteSingleRegisterResponseFrame.class);
        // 0F
        messageClasses.put(ModbusFunction.WRITE_MULTIPLE_COILS, WriteMultipleCoilsResponseFrame.class);
        // 10
        messageClasses.put(ModbusFunction.WRITE_MULTIPLE_REGISTERS, WriteMultipleRegistersResponseFrame.class);
    }

    /**
     * 根据功能码创建返回消息
     * @param functionCode 功能码
     * @return 返回消息
     */
    public static ResponseFrame createMessage(int functionCode){
        Class<? extends ResponseFrame> messageClass = ResponseFrameFactory.getMessageClass(functionCode);
        if (messageClass == null){
            throw new IllegalArgumentException("unsupported function code");
        }
        try {
            return messageClass.newInstance();
        } catch (InstantiationException | IllegalAccessException e) {
            throw new IllegalArgumentException("create message failed", e);
        }
    }
}
